#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/ipc.h>
#include <semaphore.h>
#include <fcntl.h>
#include <string.h>

#define FIFO "myfifo"
#define N 5//有界缓冲区空单元数

int lock_var;
time_t end_time;
char buf_r[100];
sem_t mutex, full, avail;
int fd;

void productor(void *arg);
void consumer(void *arg);

int main(int argc, char *argv[])
{
	pthread_t id1,id2;
	pthread_t mon_th_id;
	int ret;
	end_time = time(NULL) + 10;

	//create a named pipe
	if((mkfifo(FIFO,O_CREAT|O_EXCL) < 0) && (errno != EEXIST))
		printf("cannot create fifo server\n");
	printf("Preparing for reading bytes...\n");
	memset(buf_r, 0, sizeof(buf_r));
	//open the pipe
	fd = open(FIFO, O_RDWR|O_NONBLOCK, 0);
	if(fd == -1)
	{
		perror("open");
		exit(1);
	}
	//initialize the mutex to 1
	ret = sem_init(&mutex, 0, 1);
	//initialize the avail semaphore to N
	ret = sem_init(&avail, 0, N);
	//initialize the full semaphore to 0
	ret = sem_init(&full, 0, 0);
	if(ret != 0)
	{
		perror("sem_init");
	}
	
	//create two threads
	
	ret = pthread_create(&id1, NULL, (void*)productor, NULL);
	if(ret != 0)
	{
		perror("pthread_create productor");
	}

	ret = pthread_create(&id2, NULL, (void*)consumer, NULL);
	if(ret != 0)
	{
		perror("pthread_create consumer");
	}

	pthread_join(id1, NULL);
	pthread_join(id2, NULL);
	exit(0);

}

void productor(void *arg)
{
	int i,nwrite;
	while(time(NULL) < end_time)
	{
		//do P operation to avail and mutex
		sem_wait(&avail);
		sem_wait(&mutex);
		//the data was written by productor
		if((nwrite = write(fd, "hello", 5)) == -1)
		{
			if(errno == EAGAIN)
				printf("the FIFO has not been read yet.please try later\n");
		}
		else
			printf("write hello to the FIFO\n");
		//do V operation to full and mutex
		sem_post(&full);
		sem_post(&mutex);
		sleep(1);
	}
}

void consumer(void *arg)
{
	int nolock = 0;
	int ret,nread;
	while(time(NULL) < end_time)
	{
		//do P operation to full and mutex
		sem_wait(&full);
		sem_wait(&mutex);
		memset(buf_r, 0, sizeof(buf_r));
		if((nread = read(fd, buf_r,100)) == -1)
		{
			if(errno == EAGAIN)
			{
				printf("no data yet\n");
			}
		}
		printf("read %s from FIFO\n", buf_r);
		//do V operation to avail and mutex
		sem_post(&avail);
		sem_post(&mutex);
		sleep(1);
	}
}
